home *** CD-ROM | disk | FTP | other *** search
- /*
- File SCSI.c, the SCSI Hard Disk Installation Program
- Leo Drizis, March 1989
- Only for personal use, commercial use prohibited !!!
-
- Compile this file with THINK'S Lightspeed C
- and link it with the <stdio>, <strings> and <MacTraps> libraries
- */
-
- #include <DiskDvr.h> /* include standard definitions from C compiler */
- #include <SCSIMgr.h>
- #include <stdio.h>
- #include <strings.h>
-
- #define DEBUG1 /* change it to DEBUG to get detailed messages */
- #define PMAPLEN 9 /* length of partition map in sectors */
- #define MAXPARTS 7 /* max number od partitions */
- #define DRVRLEN 10 /* length of driver in sectors */
- #define BLKSIZE 512 /* size of sector in bytes */
- #define BLIND FALSE /* if we use blind reads/writes */
-
- #include "SCSITypes.h" /* read our typedefs */
-
- struct {
- modeSHead head;
- blockDesc blD;
- serNumPage SNPage;
- } SNPars; /* serial number parameters */
-
- struct {
- modeSHead head;
- blockDesc blD;
- geoPage geom;
- } GPars; /* geometry parameters */
-
- struct {
- modeSHead head;
- blockDesc blD;
- fmtPage fmt;
- } FPars; /* format parameters */
-
- senseData extSens;
- OSErr err; /* global error number */
- int stat,message;
- int SCSIid,interl;
- lsector lsect;
- unsigned int checkSum; /* checksum of driver */
- long rSize; /* accurate size of driver in bytes */
- SCSIInstr myTIB[3];
- Block0 blk0;
- Partition prtt;
- long capacity; /* size of hard disk in sectors */
- inqData inqPars;
- char actSerNum[10]; /* actual serial number */
- int nPart; /* number of filesystem partitions minus one */
- struct {
- long start; /* starting sector */
- long size; /* size of partition in sectors */
- Boolean changed,writeProt,hidden; /* flags */
- } Part[7];
-
- #define LONGWAIT 12*60*60 /* formatting wait in ticks */
- #define TIMEOUT 60 /* wait time in ticks for normal operations */
- #define NoErr 0
-
- #include "SCSICmds.c" /* read the low-level commands */
-
-
- Zero(ptr,howMany) /* zeroes the given space */
- char *ptr; /* pointer to the space */
- int howMany; /* size of bytes to erase */
- {
- register int i;
- for (i=0; i<howMany; i++,ptr++) *ptr = 0;
- }
-
-
-
- Boolean Yes(messg) /* asks a yes/no question displaying message */
- char *messg;
- {
- char ans[20];
-
- printf("%s [y/n] ? ",messg);
- scanf("%s",ans);
- return((ans[0] == 'y') || (ans[0] == 'Y'));
- }
-
-
- int ShowError(messg) /* displays SCSI manager errors together with a message */
- char *messg;
- {
- if (err != 0) {
- printf("Error while %s:\n",messg);
- switch (err) {
- case 2 : printf("%s\n","Communications error (operation timeout)"); break;
- case 3 : printf("%s\n","Arbitration timeout waiting for not BSY"); break;
- case 4 : printf("%s\n","Bad parameter or TIB opcode"); break;
- case 5 : printf("%s\n","SCSI bus not in correct phase for attempted operation"); break;
- case 6 : printf("%s\n","Data compare error"); break;
- case 7 : printf("%s\n","SCSI Manager busy"); break;
- case 8 : printf("%s\n","Attempted operation is out of sequence"); break;
- case 9 : printf("%s\n","CPU bus timeout"); break;
- case 10 : printf("%s\n","SCSI bus was not in Status phase"); break;
- default : printf("%s %d\n","Unknown error code = ",err); break;
- }
- printf("SCSI Status : 0x%X\n",SCSIStat() );
- }
- #ifdef DEBUG
- else printf("%s ok!\n",messg);
- #endif
- }
-
-
- myComplete(tOut) /* wait a scsi operation to complete and get status */
- long tOut; /* waiting time in ticks */
- {
- long errSect; /* the sector that caused the error */
-
- #ifdef DEBUG
- printf("Trying to complete...");
- #endif
- err=SCSIComplete(&stat,&message,tOut); /* scsi manager routine */
- #ifdef DEBUG
- printf("stat: %d messg: %d\n",stat,message);
- #endif
- if (stat == 2) { /* status 2 means that we must request sense */
- reqSen(&extSens);
- errSect=extSens.LBA_MSB*4096L + extSens.LBA_LSB; /* calc defect sector */
- printf("Sense key : 0x%X\n",extSens.senseKey);
- printf("Offending sector : %ld\n",errSect);
- printf("Additional sense code : 0x%X\n",extSens.addSenCode);
- }
- }
-
-
-
- fixBlk0() /* writes the boot sector (sector 0) */
- {
- Zero(&blk0,sizeof(blk0));
- blk0.sbSig=0x4552; /* signature */
- blk0.sbBlkSize=BLKSIZE; /* sector size of this disk */
- blk0.sbBlkCount=capacity; /* no of sectors */
- blk0.sbDevType=1;
- blk0.sbDevId=1;
- blk0.sbData=0;
- blk0.sbDrvrCount=1; /* no of drivers on this disk */
- blk0.ddBlock=PMAPLEN+1; /* starting block of driver */
- blk0.ddSize=(rSize >> 9) + 1; /* size of driver in sectors */
- blk0.ddType=1;
- write(0L,&blk0,BLKSIZE); /* write it on sector 0 */
- }
-
-
- fixPartDr() /* write the driver partition description */
- {
- Zero(&prtt,sizeof(prtt));
- prtt.pmSig=0x504D; /* partition signature */
- prtt.pmMapBlkCnt=nPart+3; /* no of sectors in partition map */
- prtt.pmPyPartStart=PMAPLEN+1; /* starting sector of partition */
- prtt.pmPartBlkCnt=DRVRLEN; /* size of partition in sectors */
- stpcpy(prtt.pmPartName,"Macintosh"); /* partition name */
- stpcpy(prtt.pmParType,"Apple_Driver"); /* partition type */
- prtt.pmDataCnt=prtt.pmPartBlkCnt;
- prtt.pmPartStatus=0x7F; /* partition flags */
- prtt.pmBootSize=rSize; /* size of driver */
- prtt.pmBootCksum=checkSum; /* checksum of driver */
- stpcpy(prtt.pmProcessor,"68000"); /* processor to execute it */
- write(1L,&prtt,BLKSIZE); /* write it on sector 1 */
- }
-
-
- fixPartMap() /* writes the partition map partition */
- {
- Zero(&prtt,sizeof(prtt));
- prtt.pmSig=0x504D;
- prtt.pmMapBlkCnt=nPart+3;
- prtt.pmPyPartStart=1;
- prtt.pmPartBlkCnt=PMAPLEN;
- stpcpy(prtt.pmPartName,"Apple");
- stpcpy(prtt.pmParType,"Apple_Partition_Map");
- prtt.pmDataCnt=prtt.pmPartBlkCnt;
- prtt.pmPartStatus=0x37;
- write(2L,&prtt,BLKSIZE); /* write it on sector 2 */
- }
-
-
- fixPartFS() /* writes the filesystem partition descriptions */
- {
- register long i,j;
-
- for (i=0; i<=nPart; i++) { /* for all defined partitions */
- Zero(&prtt,sizeof(prtt));
- prtt.pmSig=0x504D;
- prtt.pmMapBlkCnt=nPart+3;
- prtt.pmPyPartStart=Part[i].start;
- prtt.pmPartBlkCnt=Part[i].size;
- stpcpy(prtt.pmPartName,"MacOS");
- stpcpy(prtt.pmParType,"Apple_HFS");
- prtt.pmDataCnt=prtt.pmPartBlkCnt;
- prtt.pmPartStatus=0xB7;
- if (Part[i].hidden) prtt.pmPartStatus &= 0xEF; /* mark it as unreadable */
- if (Part[i].writeProt) prtt.pmPartStatus &= 0xDF; /* mark as write protected */
- write(i+3,&prtt,BLKSIZE);
- if (Part[i].changed == TRUE) { /* this partition's size/position has changed */
- printf("Partition %ld is being erased...\n",i+1);
- for (j=0; j<40; j++) { /* kill the directory writing zeros */
- Zero(lsect,sizeof(lsect));
- write(Part[i].start+2+j,lsect,BLKSIZE);
- }
- }
- }
- }
-
-
-
- ShowSectHex(ptr,howMany) /* shows a buffer on the screen for debugging */
- unsigned char *ptr; /* ptr to buffer */
- int howMany; /* no of bytes to show */
- {
- int i;
-
- for (i=1; i<=howMany; i++,ptr++) {
- printf("%2X ", *ptr);
- if ( i % 16 == 0 ) putch( '\n');
- }
- putch( '\n');
- }
-
-
- ShowSect(ptr,howMany) /* as before, but in ascii form */
- char *ptr;
- int howMany;
- {
- int i;
-
- for (i=1; i<=howMany; i++,ptr++) {
- if ( *ptr > 31 ) putch( *ptr);
- else putch( '.');
- if ( i % 64 == 0 ) putch( '\n');
- }
- }
-
-
- unsigned int calcChk(ptr,howMany) /* calculate checksum of driver */
- unsigned char *ptr;
- long howMany;
- {
- unsigned int CSum,i;
-
- for (i=0,CSum=0; i<howMany; i++,ptr++) { /* this is apple's algorithm */
- CSum = CSum + *ptr;
- asm { rol.w CSum }
- }
- if (CSum == 0) CSum = 0xFFFF;
- return(CSum);
- }
-
-
-
- InstallDriver() /* writes the driver and all boot info on the disk */
- {
- Handle hdl; /* handle to driver */
- Ptr rPtr; /* pointer to driver */
- long bNum; /* block in driver */
- int fRef; /* file reference no of driver file */
- char ans[20];
- register int i;
-
- printf("Do you really want to install driver & partitions at SCSI ID = %d [y/n] ? ",SCSIid);
- scanf("%s",ans);
- if (ans[0] != 'y' && ans[0] != 'Y') return;
- fRef=OpenResFile("\pDriver.scsi"); /* get driver file */
- hdl=GetResource('scsi',1); /* get driver resource */
- if (fRef == -1 || hdl == 0) {
- printf("Sorry, cannot find the driver resource !\n");
- err = -1;
- goto exit;
- }
- rSize=SizeResource(hdl); /* get size of this driver */
- printf("Size of driver %ld bytes.\n",rSize);
- printf("Installing driver...\n");
- HLock(hdl); /* lock this handle before dereferencing it */
- rPtr= *hdl;
- checkSum=calcChk(rPtr,rSize); /* find the checksum */
- fixBlk0(); if (err != 0) goto exit; /* write the boot block */
- fixPartMap(); if (err != 0) goto exit; /* write partition map description */
- fixPartDr(); if (err != 0) goto exit; /* write driver description */
- fixPartFS(); if (err != 0) goto exit; /* write the partitions */
- for (i=0, bNum=PMAPLEN+1; /* write driver on the disk sector for sector */
- (i <= rSize && bNum < DRVRLEN+PMAPLEN+1);
- i = i+BLKSIZE, bNum++) {
- write(bNum, (Ptr)((long)rPtr+i),BLKSIZE);
- if (err != 0) goto exit;
- }
- CloseResFile(fRef); /* we do not need the file any more */
- exit:
- if (err == 0) printf("Driver now installed, please reboot immediately.\n");
- else printf("Sorry, installing failed !\n");
- }
-
-
- char *GetSerNum() /* finds the serial number of the drive */
- {
- register int i;
-
- Zero(&actSerNum,sizeof(actSerNum));
- Zero(&inqPars,sizeof(inqPars));
- inquiry(&inqPars,sizeof(inqPars)-1);
- for (i=0; i<9; i++) actSerNum[i] = inqPars.serNum[i]; /* copy it */
- return(actSerNum);
- }
-
-
- ShowInfo() /* reads and displays all drive characteristics */
- {
- register int i;
-
- Zero(&FPars,sizeof(FPars));
- modeSen(&FPars,0x3,sizeof(FPars)); /* read format parameter page */
- if (err == 0) {
- printf("Number of Sectors : %ld\n",FPars.blD.nBlocks);
- printf("Sector Length : %ld bytes\n",FPars.blD.blkLen);
- printf("Tracks per Cylinder : %d\n",FPars.fmt.trPZone);
- printf("Spare Sectors per Cylinder : %d\n",FPars.fmt.altTrPZone);
- printf("Spare Tracks per Volume : %d\n",FPars.fmt.altTrPVol);
- printf("Sectors per Track : %d\n",FPars.fmt.secPTr);
- printf("Interleave : %d\n",FPars.fmt.iLeave);
- }
- Zero(&GPars,sizeof(GPars));
- modeSen(&GPars,0x4,sizeof(GPars)); /* read geometry page */
- if (err == 0) {
- printf("Number of Cylinders : %ld\n",GPars.geom.nCyl);
- printf("Number of Heads : %ld\n",GPars.geom.nHead);
- }
- Zero(&inqPars,sizeof(inqPars));
- inquiry(&inqPars,sizeof(inqPars)-1); /* read other parameters */
- if (err == 0) {
- printf("Revision level : %d\n",inqPars.revis);
- printf("Manufacturer : '");
- for (i=0; i<8; i++) putch(inqPars.manuf[i]);
- printf("'\n");
- printf("Model : '",inqPars.prod);
- for (i=0; i<16; i++) putch(inqPars.prod[i]);
- printf("'\n");
- printf("Serial Number : '%s'\n",GetSerNum());
- printf("Hardware revision level : %d\n",inqPars.hardRev);
- printf("Firmware revision level : %d\n",inqPars.firmRev);
- printf("ROM revision level : %d\n",inqPars.ROMRev);
- }
- ShowDefs(); /* count the defect sectors */
- }
-
-
- ShowDefs() /* counts the defect sectors on the disk */
- {
- unsigned long defects[512]; /* defects table */
- int defCnt,blCnt;
- Boolean nuDefs; /* if we have found user defined defects */
- register int i;
-
- Zero(defects,sizeof(defects));
- ReadDefect(defects,sizeof(defects)); /* issue read defect command */
- if (err != 0) return;
- nuDefs=FALSE;
- blCnt=(defects[0]&0x0000FFFF)>>2; /* calculate no of entries in def. list */
- for (i=1,defCnt=0; i <= blCnt; i++) {
- if (defects[i] == 0xFFFFFFFF) { /* this is the start of user defined defects */
- nuDefs=TRUE;
- continue;
- }
- defCnt++;
- if (nuDefs) i++; /* usr defects are double entries, so adjust */
- }
- printf("Number of KNOWN (and set aside) bad sectors: %d\n",defCnt);
- }
-
-
- my_Menu(menu,item) /* handle menu selections */
- /* THIS FUNCTION IS CALLED FROM stdio'S StdEvent() FUNCTION */
- short menu,item;
- {
- if (menu == 4) { /* SCSI menu */
- printf("\f");
- switch (item) {
- case 1:
- SearchDrives();
- break;
- case 2:
- EnterID();
- break;
- case 3:
- Format();
- break;
- case 4:
- PartDefine();
- break;
- case 5:
- InstallDriver();
- break;
- case 6:
- ShowInfo();
- break;
- }
- printf("Done !\n");
- }
- }
-
-
-
- SearchDrives() /* looks for connected drives */
- {
- int oldID,nDrives,lastID;
-
- oldID=SCSIid; /* save current id */
- printf("Searching for connected drives...\n");
- for (SCSIid=0,nDrives=0; SCSIid<7; SCSIid++) {
- capacity=Capacity(); /* get capacity of this drive */
- if (capacity > 0) { /* if this drive exists... */
- nDrives++; /* one more drive found */
- lastID=SCSIid; /* save last drive found */
- printf("At SCSI ID %d, capacity %ld kBytes.\n",SCSIid,capacity>>1);
- }
- }
- if (nDrives == 0) printf("No drives connected !\n");
- if (oldID == -1) SCSIid=lastID; /* id is last drive found */
- else SCSIid=oldID; /* id remains the same */
- }
-
-
-
- EnterID() /* asks the user for an scsi id */
- {
- int newID;
-
- do {
- printf("Enter the SCSI ID number (now %d), or -1 for no change : ",SCSIid);
- scanf("%d",&newID);
- if (newID == -1) break;
- SCSIid = newID;
- capacity=Capacity(); /* get drive's size */
- nPart = 0; /* one partition is default */
- Zero(Part, sizeof(Part));
- Part[0].start = DRVRLEN+PMAPLEN+1; /* default start after part. map */
- Part[0].changed = TRUE; /* must zero this partition */
- Part[0].hidden = FALSE;
- Part[0].writeProt = FALSE;
- Part[0].size = capacity - (DRVRLEN+PMAPLEN+1);
- /* default size is all disk */
- if (capacity == 0) printf("No such drive connected !\n");
- else printf("This is a %ld kByte hard Disk.\n",capacity>>1);
- }
- while (capacity == 0 || !Yes("\nIs the SCSI ID correct")); /* until correct */
- printf("SCSI ID is now %d.\n",SCSIid);
- }
-
-
-
- PartDefine() /* define all partitions' characteristics */
- {
- long i;
- long currFree,curr1Free,currSize;
-
- printf("Current Partition Info:\n");
- for (i=0; i<=nPart; i++) { /* for all partitions */
- read(i+3,&prtt,BLKSIZE); /* read part. description from disk */
- if (prtt.pmSig == 0x504D && strcmp(prtt.pmParType,"Apple_HFS") == 0 ) {
- /* we found a filesystem partition */
- nPart = prtt.pmMapBlkCnt - 3; /* get the real no of parts. */
- Part[i].start = prtt.pmPyPartStart;
- Part[i].size = prtt.pmDataCnt;
- Part[i].changed = FALSE;
- Part[i].hidden = ((prtt.pmPartStatus & 0x0010) == 0);
- Part[i].writeProt = ((prtt.pmPartStatus & 0x0020) == 0);
- }
- printf("No %ld, Starting Sector : %ld, size : ",i+1,Part[i].start);
- printf("%ld kBytes",Part[i].size>>1);
- if (Part[i].hidden) printf(" Hidden");
- if (Part[i].writeProt) printf(" Protected");
- printf("\n");
- }
- if (Yes("Do you want to change the Partition info")) {
- curr1Free = DRVRLEN+PMAPLEN+1; /* actual first free sector */
- currFree = capacity - curr1Free; /* actual free size */
- printf("Enter new number of Partitions (max 7) : ");
- scanf("%d",&nPart); nPart--; /* minus one */
- for (i=0; i<=nPart && i<=MAXPARTS; i++) {
- do {
- printf("Partition No. %ld, %ld kBytes free.\n",i+1,currFree>>1);
- printf("Enter size of this Partition in kBytes: ");
- scanf("%ld",&currSize);
- currSize <<= 1; /* make it in sectors */
- if (currFree<currSize) printf("Not so much place free !\n");
- if (currSize < 1024) printf("Partitions cannot be so small !\n");
- }
- while (currFree<currSize && currSize<1024); /* until correct */
- Part[i].hidden = Yes("Is this Partition hidden");
- Part[i].writeProt = Yes("Is this Partition write protected");
- if (Part[i].start != curr1Free || Part[i].size != currSize) {
- /* if size or position of this part. changed */
- Part[i].start = curr1Free;
- Part[i].size = currSize;
- Part[i].changed = TRUE; /* mark it for erasing */
- }
- curr1Free += currSize; /* adjust 1st free for next part. */
- currFree -= currSize; /* adjust free size for next part. */
- if (currFree <= 0) { nPart = i; break; } /* no free size left */
- }
- }
- }
-
-
- main()
- {
- register MenuHandle menu; /* handle for our menus */
-
- SCSIid = -1;
- printf("\f"); /* has the side effect of initialising the stdio ! */
- printf("\nHard Disk Utility Program, v1.00\n");
- printf("\nCopyright Leo Drizis, March '89\n\n");
- menu = NewMenu(4, "\pSCSI"); /* get a new menu */
- AppendMenu(menu, "\pSearch Drives;Change Drive;Format;Partitions;Install;Disk Info;");
- /* add entries to menu */
- InsertMenu(menu, 0); /* put it together with other menus */
- DrawMenuBar(); /* make menu visible */
- /* err=SCSIReset(); for the 1st time init the scsi bus */
- ShowError("resetting");
- SearchDrives(); /* for the 1st time search for drives */
- EnterID(); /* for the 1st time ask for scsi id */
- printf("Done !\n");
- for (;;) { /* a small event loop to handle events */
- EventRecord event;
- while (! GetNextEvent(everyEvent, &event)) { /* no events, wait */
- HiliteMenu(0);
- SystemTask(); /* allow background tasks to continue */
- }
- SetCursor(&arrow); /* reset cursor to arrow */
- StdEvent(&event); /* call stdio's event handler */
- }
- }
-